<?php
//MD5签名==========================================================================================================================================
use app\utils\Log;

function md5_sign($data, $secret, $includeEmptyParam = false, $upper = false, $useTrim = false)
{
    $content = arr_to_urlparams($data, $includeEmptyParam, $useTrim) . '&key=' . $secret;
    $result = md5($content);
    if ($upper) {
        $result = strtoupper($result);
    }
    return $result;
}

function md5_verify($data, $sign, $secret, $includeEmptyParam = false, $upper = false, $useTrim = false)
{
    if (empty($secret)) {
        return false;
    }
    $content = arr_to_urlparams($data, $includeEmptyParam, $useTrim) . '&key=' . $secret;
    $result = md5($content);
    if ($upper) {
        return strtoupper($result) == $sign;
    } else {
        return $result == $sign;
    }
}

function arr_to_urlparams($data, $includeEmptyParam = false, $useTrim = false)
{
    if (is_string($data)) {
        Log::info('签名或验签内容：' . $data);
        return $data;
    }
    Log::info('签名或验签内容：' . json_encode($data));
    if (!empty($data)) {
        $p = ksort($data);
        if ($p) {
            $str = '';
            foreach ($data as $k => $val) {
                if (strtolower($k) == 'sign' || strtolower($k) == 'signtype' || strtolower($k) == 'sign_type') {
                    continue;
                }
                if ($includeEmptyParam) {
                    $str .= $k . '=' . ($useTrim ? trim($val) : $val) . '&';
                } elseif ($val !== '') {
                    $str .= $k . '=' . ($useTrim ? trim($val) : $val) . '&';
                }
            }
            $strs = rtrim($str, '&');
            return $strs;
        }
    }
    return '';
}

//RSA签名与验签===============================================================================================================
function rsa_sha1_sign($data, $private_key)
{
    if (substr_count($private_key, '-----BEGIN') === 0) {
        $private_key = "-----BEGIN PRIVATE KEY-----\n" . $private_key . "\n-----END PRIVATE KEY-----";
    }
    $signature = '';
    openssl_sign($data, $signature, $private_key);
    return base64_encode($signature);
}

function rsa_sha1_verify($data, $sign, $public_key)
{
    if (substr_count($public_key, '-----BEGIN') === 0) {
        $public_key = "-----BEGIN PUBLIC KEY-----\n" . $public_key . "\n-----END PUBLIC KEY-----";
    }
    $signature = base64_decode($sign);
    $ok = openssl_verify($data, $signature, $public_key);
    if ($ok === 1) {
        return true;
    }
    return false;
}

//AES加密===============================================================================================================
function aes_encrypt($content, $key, $iv)
{
    if (!is_string($content)) {
        Log::error('aes_encode() must input string, current is array!');
        return null;
    }
    return openssl_encrypt($content, 'aes-256-cbc', $key, 0, $iv);
}

//AES解密
function aes_decrypt($content, $key, $iv)
{
    if (!is_string($content)) {
        Log::error('aes_decrypt() must input string, current is array!');
        return null;
    }
    return openssl_decrypt($content, 'aes-256-cbc', $key, 0, $iv);
}

//Http GET协程===================================================================================================================
function http_get_coroutine($url, $header = null)
{
    $http = new Workerman\Http\Client();
    $h = ['method' => 'GET'];
    if ($header != null) {
        foreach ($header as $k => $v){
            $h[$k] = $v;
        }
    }
    $res = $http->request($url, ['headers' => $h])->getBody();
    return $res . '';
}

//Http POST协程
function http_post_coroutine($url, $data, $json_content_type = true, $header = null)
{
    $http = new Workerman\Http\Client();
    $params = $json_content_type ? json_encode($data) : $data;
    $h = [
        'Connection' => 'keep-alive',
        'Content-Type' => $json_content_type ? 'application/json' : 'application/x-www-form-urlencoded',
    ];
    if ($header != null) {
        foreach ($header as $k => $v){
            $h[$k] = $v;
        }
    }
    $res = $http->request($url, [
        'method' => 'POST',
        'headers' => $h,
        'data' => $params,
    ])->getBody();
    return $res . '';
}

//Http GET异步
function http_get_async($url, $success = null, $error = null)
{
    $http = new Workerman\Http\Client();
    if ($success == null) {
        $success = function ($res) {
        };
    }
    if ($error == null) {
        $error = function ($err) {
        };
    }
    $http->get($url, $success, $error);
}

//Http POST同步
function http_post_sync($url, $data, $isJson = true, $headers = [])
{
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_POST, true);
    if ($isJson) {
        $payload = json_encode($data);
        $headers[] = 'Content-Type: application/json';
    } else {
        $payload = $data;
    }
    curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
    if (!empty($headers)) {
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    }
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $response = curl_exec($ch);
    if ($response === false) {
        $error = curl_error($ch);
        curl_close($ch);
        throw new Exception("cURL error: $error");
    }
    curl_close($ch);
    return $response;
}

//Http POST异步
function http_post_async($url, $data, $json_content_type = true, $success = null, $error = null)
{
    $http = new Workerman\Http\Client();
    if ($success == null) {
        $success = function ($res) {
        };
    }
    if ($error == null) {
        $error = function ($err) {
        };
    }
    $params = $json_content_type ? json_encode($data) : $data;
    $http->request($url, [
        'method' => 'POST',
        'headers' => [
            'Connection' => 'keep-alive',
            'Content-Type' => $json_content_type ? 'application/json' : 'application/x-www-form-urlencoded',
        ],
        'data' => $params,
        'success' => $success,
        'error' => $error,
    ]);
}

//常规GET请求
function http_get($url)
{
    //忽略ssl证书，使http也能访问
    $arrContextOptions = ["ssl" => ["verify_peer" => false, "verify_peer_name" => false, "allow_self_signed" => true]];
    return file_get_contents($url, false, stream_context_create($arrContextOptions));
}

//字符串操作===============================================================================================================================================
function tojson($data)
{
    if (!is_string($data)) {
        return json_encode($data);
    }
    return $data;
}

function isjson($data)
{
    return is_string($data) && substr($data, 0, 1) == '{';
}

function contains($str, $needle)
{
    return strpos($str, $needle) !== false;
}

function start_with($str, $prefix)
{
    return substr($str, 0, strlen($prefix)) == $prefix;
}

function end_with($str, $suffix)
{
    return substr($str, -strlen($suffix)) == $suffix;
}

function isnumber($str)
{
    if (is_numeric($str) && preg_match('/^[0-9]+$/', $str)) {
        return true;
    }
    return false;
}

function toint($str)
{
    return intval($str);
}

function tofloat($str)
{
    return floatval($str);
}

//<textarea> 文本框输入的空格和换行，从mysql读取时需要转换再发给客户端
function strSpaceAndBr($content)
{
    return nl2br(str_replace(" ", "&nbsp;", $content));
}

//时间操作================================================================================================================================
function time_ms()
{
    [$msec, $sec] = explode(' ', microtime());
    return (float)sprintf('%.0f', (floatval($msec) + floatval($sec)) * 1000);
}

//图片操作(成功返回true失败返回false)=======================================================================================================
function img_save_with_base64($path, $base64)
{
    $dir = dirname($path);
    if (!is_dir($dir)) {
        mkdir($dir);
    }
    $imageData = base64_decode($base64);
    return file_put_contents($path, $imageData);
}

//失败返回null
function img_read_as_base64($path)
{
    if (is_file($path)) {
        $imageData = file_get_contents($path);
        return base64_encode($imageData);
    }
    return null;
}

//按天的范围查询数据库时，时间自动标准化=========================================================================================================================================
function first_day_this_month()
{
    return date("y-m-d", strtotime("first day of this month"));
}

function last_day_this_month()
{
    return date("y-m-d", strtotime("last day of this month"));
}

function format_start_date($date)
{
    if (empty($date)) {
        return date('Y-m-d') . ' 00:00:00';
    }
    return date('Y-m-d', strtotime($date)) . ' 00:00:00';
}

//格式化结束时间参数
function format_end_date($date)
{
    if (empty($date)) {
        return date('Y-m-d') . ' 23:59:59';
    }
    return date('Y-m-d', strtotime($date)) . ' 23:59:59';
}

//读取系统环境变量=========================================================================================================================================
function get_sys_env_value($name, $default = null) {
    // 尝试从 $_SERVER 获取
    $value = $_SERVER[$name] ?? null;
    // 如果 $_SERVER 中没有，尝试 getenv()
    if ($value === null) {
        $value = getenv($name);
    }
    // 如果还是没有找到，尝试使用特定于操作系统的命令
    if ($value === false || $value === null) {
        if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
            // Windows 系统
            $value = shell_exec('echo %' . $name . '%');
            if ($value !== null) {
                $value = trim($value);
                // 如果返回的是变量名本身，说明变量不存在
                if ($value === '%' . $name . '%') {
                    $value = $default;
                }
            }
        } else {
            // Linux/Unix 系统
            $value = shell_exec('echo $' . $name);
            if ($value !== null) {
                $value = trim($value);
                // 如果返回空字符串，可能变量不存在
                if ($value === '') {
                    $value = $default;
                }
            }
        }
    }
    // 如果所有尝试都失败，返回默认值
    return $value !== false && $value !== null ? $value : $default;
}